package tau.dimes.visualization.applet.topology;

import java.util.Map;

import processing.core.PApplet;
import tau.dimes.visualization.applet.DimesVApplet;
import tau.dimes.visualization.applet.Parameters;
import tau.dimes.visualization.applet.data.Edge;

/**
 * Represents an arc in the topology visualization.
 */
public class TopologyArc
{
	private final PApplet applet;

	private float x;
	private float y;
	private float r;
	private float startAngle;
	private float endAngle;
	private TopologyNode source;
	private TopologyNode destination;

	/**
	 * Constructs a new TopologyArc.
	 * @param applet A reference to the containing applet.
	 * @param edge The underlying Edge object.
	 * @param nodes A reference to the map of nodes.
	 */
	public TopologyArc(PApplet applet, Edge edge, Map<String, TopologyNode> nodes)
	{
		this.applet = applet;
		this.source = nodes.get(edge.getSource().getId());
		this.destination = nodes.get(edge.getDestination().getId());
		calculate();
	}

	private void calculate()
	{
		float x1 = source.getX();
		float y1 = source.getY();
		float x2 = destination.getX();
		float y2 = destination.getY();

		this.r = PApplet.dist(x1, y1, x2, y2);

		float angle;
		if (x1 != x2)
			angle = (float)Math.atan((y2 - y1) / (x2 - x1));
		else if (y2 > y1)
			angle = (float)Math.PI / 2;
		else
			angle = -(float)Math.PI / 2;
		if (x1 > x2)
			angle += Math.PI / 3;
		this.x = x1 + this.r * (float)Math.cos(angle + Math.PI / 3);
		this.y = y1 + this.r * (float)Math.sin(angle + Math.PI / 3);
		this.startAngle = angle + (float)(4 * Math.PI / 3);
		if (x1 > x2)
			this.endAngle = this.startAngle - DimesVApplet.PI / 3;
		else
			this.endAngle = this.startAngle + DimesVApplet.PI / 3;
	}

	/**
	 * Draws the graphical representation of the arc.
	 * @param stage Arc drawing stage.
	 * @param alpha Alpha value (see Clock class).
	 */
	public void draw(ArcDrawStage stage, float alpha)
	{
		float angle;
		
		if (stage == ArcDrawStage.Full)
			alpha = 1.0F;

		angle = PApplet.map(alpha, 0, 1, startAngle, endAngle);
	
		switch(stage)
		{
		case Deleted:
			if (Parameters.fadeButKeep())
			{
				applet.stroke(255, 127, 0, 0.25F * 255.0F);
				if (startAngle < endAngle)
					applet.arc(x, y, r * 2, r * 2, startAngle, endAngle);
				else
					applet.arc(x, y, r * 2, r * 2, endAngle, startAngle);
			}
			break;
		case Full:
		case Drawing:
			source.setReached(true);
			if (alpha == 1.0F)
				destination.setReached(true);
			applet.stroke(255, 127, 0, alpha * 255.0F);
			if (startAngle < angle)
				applet.arc(x, y, r * 2, r * 2, startAngle, angle);
			else
				applet.arc(x, y, r * 2, r * 2, angle, startAngle);
			break;
		case Deleting:
			destination.setReached(true);
			if (Parameters.fadeButKeep())
				applet.stroke(255, 127, 0, (1 - (0.75F * alpha)) * 255.0F);
			else
				applet.stroke(255, 127, 0, (1 - alpha) * 255.0F);
			if (startAngle < endAngle)
				applet.arc(x, y, r * 2, r * 2, startAngle, endAngle);
			else
				applet.arc(x, y, r * 2, r * 2, endAngle, startAngle);
			break;
		}
	}
}